package com.yoso.shop.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.yoso.base.infrastructure.exception.BaseException;
import com.yoso.base.infrastructure.utils.IdUtil;
import com.yoso.base.interfaces.controller.BaseResponse;
import com.yoso.base.service.BaseService;
import com.yoso.shop.application.service.ICommodityService;
import com.yoso.shop.application.service.IDictionaryService;
import com.yoso.shop.application.service.IStockService;
import com.yoso.shop.domain.commodity.CommodityEntity;
import com.yoso.shop.domain.commodity.CommodityEntityExample;
import com.yoso.shop.domain.dictionary.DictionaryEntityExample;
import com.yoso.shop.infrastructure.cache.CommodityCacheServer;
import com.yoso.shop.infrastructure.constants.commodity.DictionaryGroupEnums;
import com.yoso.shop.infrastructure.constants.commodity.StaticResourcesPath;
import com.yoso.shop.infrastructure.factory.ShopBeanFactory;
import com.yoso.shop.infrastructure.utils.UploadUtils;
import com.yoso.shop.interfaces.vo.commodity.CommodityVo;
import com.yoso.shop.interfaces.vo.dictionary.DictionaryVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author shizejin
 * @date 2022/1/30
 * @description:
 */
@Service
@Slf4j
public class CommodityServiceImpl extends BaseService<CommodityEntity, CommodityVo, CommodityEntityExample> implements ICommodityService {
    @Autowired
    private UploadUtils uploadUtils;
    @Autowired
    private IDictionaryService dictionaryService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private CommodityCacheServer commodityCacheServer;

    @Override
    public CommodityEntity V2E(CommodityVo data) {
        return JSON.parseObject(JSON.toJSONString(data), CommodityEntity.class);

    }

    @Override
    public CommodityVo E2V(CommodityEntity data) {
        return JSON.parseObject(JSON.toJSONString(data), CommodityVo.class);
    }

    @Override
    public CommodityEntityExample getEntityExample(Map<String, String> paramMap) {
        return null;
    }

    @Override
    public CommodityVo findByCode(String commodityCode) {
        CommodityEntityExample example = new CommodityEntityExample();
        example.createCriteria().andCodeEqualTo(commodityCode);

        List<CommodityVo> vos = this.selectByExample(example);
        if (CollectionUtils.isEmpty(vos)) {
            log.error("没有该商品，代码:{}", commodityCode);
            return null;
        }
        return vos.get(0);
    }

    @Override
    @Transactional(rollbackFor = BaseException.class)
    public CommodityVo saveOrUpdate(CommodityVo vo) {
        String id = vo.getId();
        vo.setUpdateTime(DateUtil.now());
        if (StringUtils.isBlank(id)) {
            vo.setCreatTime(DateUtil.now());
            vo.setCode(IdUtil.buildCommodityId());
            log.info("增加库存:{}", JSON.toJSONString(vo));
            stockService.addStock(ShopBeanFactory.buildStockVo(vo), "新品增加", "");
        }
//        商品标签
        List<String> tags = vo.getTags();
        if (CollUtil.isNotEmpty(tags)) {
//                商品标签信息入库
            if (CollUtil.isNotEmpty(tags)) {
                DictionaryVo tagVo = new DictionaryVo();
                tagVo.setType(DictionaryGroupEnums.COMMODITY_TAG.toString());
                tagVo.setTag(vo.getCode() + DictionaryGroupEnums.COMMODITY_TAG_SUF);
                tagVo.setInfo(String.join(",", tags));
                dictionaryService.insert(tagVo);
            }
        }
        this.insert(vo);
//        重新加载缓存
        commodityCacheServer.init();
        return this.selectByPrimaryKey(vo.getId());
    }

    /**
     * 新增商品信息
     */
    @Override
    @Transactional(rollbackFor = BaseException.class)
    public BaseResponse saveNewCommodityInfo(CommodityVo commodityVo, MultipartFile[] photos) {
        commodityVo = this.saveOrUpdate(commodityVo);
        List<String> photoUrlList = CollUtil.newArrayList();
//         处理图片
        for (MultipartFile photo : photos) {
            if (photo.getSize() <= 0) {
                continue;
            }
            String originalFilename = photo.getOriginalFilename();
            int index = originalFilename.lastIndexOf(".");
            String foot = originalFilename.substring(index);
            String fileName = RandomUtil.randomNumbers(6) + foot;
            photoUrlList.add(uploadUtils.buildPhotoUrl(StaticResourcesPath.COMMODITY_PATH, fileName));
            try {
                photo.transferTo(uploadUtils.getPath(StaticResourcesPath.COMMODITY_PATH, fileName));
            } catch (IOException e) {
                log.error("{}的图片上传失败！！！", commodityVo.getName());
                throw new BaseException(e.getMessage());
            }
        }
//                商品图片信息入库
        DictionaryVo photoVo = new DictionaryVo();
        photoVo.setType(DictionaryGroupEnums.COMMODITY_PHOTO.toString());
        photoVo.setTag(commodityVo.getCode() + DictionaryGroupEnums.COMMODITY_PHOTO_SUF);
        photoVo.setInfo(String.join(",", photoUrlList));
        dictionaryService.insert(photoVo);
        return this.success();
    }

    /**
     * 获取主页主分类展示数据（轮播图上）
     */
    @Override
    public Map<String, List<CommodityVo>> getShowMasterCommodityData() {
//        todo:获取属于该分类的所有商品。日后将推荐商品放在字典表中
        List<CommodityVo> listAll = this.listAll();
        if (CollUtil.isEmpty(listAll)) {
            return CollUtil.newHashMap(0);
        }
        String photo = DictionaryGroupEnums.COMMODITY_PHOTO.toString();
        String tag = DictionaryGroupEnums.COMMODITY_TAG.toString();
        List<DictionaryVo> photoList = dictionaryService.getDataByGroup(photo);
        List<DictionaryVo> tagList = dictionaryService.getDataByGroup(tag);

//        commodityCode - dic
        Map<String, DictionaryVo> commodityPhotoMap = photoList.parallelStream().
                collect(Collectors.toMap(
//                        123_photo -> 123
                        e -> StringUtils.substring(e.getTag(), 0, e.getTag().indexOf(DictionaryGroupEnums.COMMODITY_PHOTO_SUF.toString())),
                        Function.identity(),
                        (v1, v2) -> v2
                ));


//        commodityCode - dic
        Map<String, DictionaryVo> commodityTagMap = tagList.parallelStream().
                collect(Collectors.toMap(
//                        123_tag -> 123
                        e -> StringUtils.substring(e.getTag(), 0, e.getTag().indexOf(DictionaryGroupEnums.COMMODITY_TAG_SUF.toString())),
                        Function.identity(),
                        (v1, v2) -> v2
                ));


//        循环遍历商品信息，填入图片和标签信息
        for (CommodityVo data : listAll) {
            String code = data.getCode();
            DictionaryVo photoVo = commodityPhotoMap.get(code);
            if (ObjectUtils.isNotEmpty(photoVo)) {
                data.setPhotoPathList(Arrays.asList(photoVo.getInfo().split(",")));
            }
            DictionaryVo tagVo = commodityTagMap.get(code);
            if (ObjectUtils.isNotEmpty(tagVo)) {
                data.setTags(Arrays.asList(tagVo.getInfo().split(",")));
            }
        }
        return listAll.parallelStream().collect(Collectors.groupingBy(CommodityVo::getMaster));
    }

    /**
     * 根据id查询商品，包括字典表中的图片和标签
     */
    @Override
    public CommodityVo findDetailInfoById(String id) {
        CommodityVo commodityVo = this.selectByPrimaryKey(id);
        String photo = DictionaryGroupEnums.COMMODITY_PHOTO.toString();
        String tag = DictionaryGroupEnums.COMMODITY_TAG.toString();
        String photoSuf = DictionaryGroupEnums.COMMODITY_PHOTO_SUF.toString();
        String tagSuf = DictionaryGroupEnums.COMMODITY_TAG_SUF.toString();
        DictionaryEntityExample example = new DictionaryEntityExample();
        example.createCriteria()
                .andTypeIn(Arrays.asList(photo, tag))
                .andTagLike(commodityVo.getCode() + "%");
        List<DictionaryVo> dictionaryVos = dictionaryService.selectByExample(example);
        for (DictionaryVo vo : dictionaryVos) {
            String tag1 = vo.getTag();
            String info = vo.getInfo();
            if (StringUtils.contains(tag1, tagSuf)) {
                commodityVo.setTags(Arrays.asList(info.split(",")));
            }
            if (StringUtils.contains(tag1, photoSuf)) {
                commodityVo.setPhotoPathList(Arrays.asList(info.split(",")));
            }
        }
        return commodityVo;
    }

    /**
     * 根据商品代码查询商品，包括字典表中的图片和标签
     *
     * @param code 商品代码
     */
    @Override
    public CommodityVo findDetailInfoByCode(String code) {
        CommodityVo vo = this.findByCode(code);
        vo.setPhotoPathList(buildCommodityCodeToPhotoPathListMap().get(code));
        vo.setTags(buildCommodityCodeToTagListMap().get(code));
        return vo;
    }

    /**
     * 构建商品详细信息，增加字典表中的图片和标签
     */
    @Override
    public List<CommodityVo> buildDetailInfoList(Iterable<CommodityVo> commodityVos) {
        ArrayList<CommodityVo> result = CollUtil.newArrayList();

        Map<String, List<String>> commodityCode2photoPathListMap = this.buildCommodityCodeToPhotoPathListMap();
        Map<String, List<String>> commodityCode2tagListMap = this.buildCommodityCodeToTagListMap();
        for (CommodityVo vo : commodityVos) {
            String code = vo.getCode();
            vo.setTags(commodityCode2tagListMap.get(code));
            vo.setPhotoPathList(commodityCode2photoPathListMap.get(code));
            result.add(vo);
        }
        return result;
    }

    /**
     * @param group    数据分组 eg: 商品图片
     * @param photoSuf tag后缀 eg: _photo
     */
    @NotNull
    @Override
    public Map<String, List<String>> buildCommodityCodeToSomeListMap(String group, String photoSuf) {
        DictionaryEntityExample example = new DictionaryEntityExample();
        example.createCriteria()
                .andTypeEqualTo(group)
                .andTagLike("%" + photoSuf);
        List<DictionaryVo> dictionaryVos = dictionaryService.selectByExample(example);
        if (CollUtil.isEmpty(dictionaryVos)) {
            return Maps.newHashMap();
        }
        return dictionaryVos.parallelStream().collect(Collectors.toMap(
                vo -> StringUtils.substring(vo.getTag(), 0, vo.getTag().indexOf(photoSuf)),
                vo -> Arrays.asList(vo.getInfo().split(","))
        ));
    }

    /**
     * @return code：自身
     */
    @Override
    public Map<String, CommodityVo> buildCommodityCodeToSelfMap() {
        return this.listAll().parallelStream()
                .collect(Collectors.toMap(
                        CommodityVo::getCode,
                        Function.identity(),
                        (v1, v2) -> v2
                ));
    }

    /**
     * @return 获取商品颜色和大小集合
     */
    @Override
    public Map<String, List<DictionaryVo>> getCommodityColorSizeListMap() {
        String size = DictionaryGroupEnums.SIZE.toString();
        String color = DictionaryGroupEnums.COLOR.toString();
        DictionaryEntityExample example = new DictionaryEntityExample();
        example.createCriteria()
                .andTypeIn(Arrays.asList(size, color));
        List<DictionaryVo> dictionaryVos = dictionaryService.selectByExample(example);
        return dictionaryVos.parallelStream().collect(
                Collectors.groupingBy(DictionaryVo::getType)
        );
    }

    /**
     * @return 商品代码 ： 图片访问路径集合
     */
    private Map<String, List<String>> buildCommodityCodeToPhotoPathListMap() {
        String photo = DictionaryGroupEnums.COMMODITY_PHOTO.toString();
        String photoSuf = DictionaryGroupEnums.COMMODITY_PHOTO_SUF.toString();
        return buildCommodityCodeToSomeListMap(photo, photoSuf);
    }

    /**
     * @return 商品代码 ： 商品标签集合
     */
    private Map<String, List<String>> buildCommodityCodeToTagListMap() {
        String tag = DictionaryGroupEnums.COMMODITY_TAG.toString();
        String tagSuf = DictionaryGroupEnums.COMMODITY_TAG_SUF.toString();
        return buildCommodityCodeToSomeListMap(tag, tagSuf);
    }

    @Override
    public List<CommodityVo> listAll() {
        List<CommodityVo> commodityVos = super.listAll();
        return buildDetailInfoList(commodityVos);
    }
}
